/*
 * Copyright (c) 2019.11，华乘电气科技有限公司
 * All rights reserved.
 *
 * 文件名称：dataspecification.h
 * 
 * 初始版本：1.0
 * 作者：洪澄
 * 创建日期：2019/11/04
 * 摘要：数据规范
 * 当前版本：1.0
 */

 /*接口使用示例：
  1.数据生成保存
    DataSpecification dataSpecification;
    // 设置版本号
    dataSpecification.setDataSpecificationVersion(DataSpecificationGW::V_4_1_0_2);
    dataSpecification.setStationName(...);
    ...
    AEAmpSpectrum* pAEAmpSpectrum = new AEAmpSpectrum();
    pAEAmpSpectrum->setEquipmentName(...);
    ....
    AEAmpExtInformation stAEAmpExtInformation;
    stAEAmpExtInformation.eAmpUnit = ...;
    ...
    pAEAmpSpectrum->setAEAmpExtInformation(stAEAmpExtInformation);

    //生成data
    AEAmpData stAEAmpData;
    stAEAmpData.fSignalMax = ...;
    ...
    pAEAmpSpectrum->setAEAmpData(stAEAmpData);

    dataSpecification.addSpectrum(pAEAmpSpectrum);
    dataSpecification.saveAsBinary(...);
    dataSpecification.saveAsXML(...);
    dataSpecification.saveAsJSON(...);

  2.数据读取
    DataSpecification dataSpecification;
    // 设置版本号
    dataSpecification.setDataSpecificationVersion(DataSpecificationGW::V_4_1_0_2);
    dataSpecification.parseBinaryFromFile(...);
    dataSpecification.parseJSONFromFile(...);
    dataSpecification.parseXMLFromFile(...);


     QList<DataMap::MapHead> headers = dataFile.mapsHeadList();
     //根据headers的内容确定自己所读取图谱的索引
     DataMap * pMap = dataFile.dataMap( iMapPos );
     AEPhaseDataMap * pAePhase = dynamic_cast<AEPhaseDataMap *>(pMap);

     pAePhase->getDeviceName(...)
     ...
     AEMapNS::AEPhaseMapInfo mapInfo;
     pAePhase->getInfo( &mapInfo );
     double * pAePhaseData = new double[..];
     pAePhase->getData( pAePhaseData );
 */

#pragma once

#include <QByteArray>
#include <vector>
#include "spectrum.h"
#include "dataspecification_global.h"
#include "dataspecification_def.h"
#include "spectrumdatafiledefine.h"
#include "include/rapidjson/rapidjson.h"
#include "include/rapidjson/document.h"

namespace DataSpecificationGW
{
    class DataSpecificationPrivate;
    class XMLDocument;
    class Spectrum;
    class DATASPECIFICATIONSHARED_EXPORT DataSpecification
    {
    public:
        DataSpecification();
        ~DataSpecification();

        /************************************************
         * 函数名   : setDataSpecificationVersion
         * 输入参数 :
           const DataSpecificationVersion eDataSpecificationVersion: 数据规范版本号
         * 输出参数 : NULL
         * 返回值   : void
         * 功能     : 设置数据规范版本号
         ************************************************/
        inline void setDataSpecificationVersion(const DataSpecificationVersion eDataSpecificationVersion) { m_eDataSpecificationVersion = eDataSpecificationVersion; }

        /************************************************
         * 函数名   : dataSpecificationVersion
         * 输入参数 : NULL
         * 输出参数 : NULL
         * 返回值   : DataSpecificationVersion
         * 功能     : 获取数据规范版本号
         ************************************************/
        inline DataSpecificationVersion dataSpecificationVersion() { return m_eDataSpecificationVersion; }

        /************************************************
         * 函数名   : addSpectrum
         * 输入参数 :
           Spectrum* pSpectrum: 图谱指针
         * 输出参数 : NULL
         * 返回值   : int
         * 功能     : 添加图谱
         ************************************************/
        int addSpectrum(Spectrum* pSpectrum);

        /************************************************
         * 函数名   : spectrum
         * 输入参数 :
           const int iIndex: 索引
         * 输出参数 : NULL
         * 返回值   : Spectrum*
         * 功能     : 获取指定位置图谱的指针
         ************************************************/
        Spectrum* spectrum(const int iIndex);

        /************************************************
         * 函数名   : spectrum
         * 输入参数 :
           const SpectrumTypeCode eSpectrumCode: 图谱类型编码
         * 输出参数 : NULL
         * 返回值   : Spectrum*
         * 功能     : 获取特定类型的图谱的指针
         ************************************************/
        Spectrum* spectrum(const SpectrumTypeCode eSpectrumCode);

        /************************************************
         * 函数名   : spectrums
         * 输入参数 : NULL
         * 输出参数 : NULL
         * 返回值   : std::vector<Spectrum*>
         * 功能     : 获取所有图谱的指针
         ************************************************/
        std::vector<Spectrum*> spectrums();

        /************************************************
         * 函数名   : spectrums
         * 输入参数 :
           const SpectrumTypeCode eSpectrumCode: 图谱类型编码
         * 输出参数 : NULL
         * 返回值   : Spectrum*
         * 功能     : 获取特定类型的图谱的指针
         ************************************************/
        std::vector<Spectrum*> spectrums(const SpectrumTypeCode eSpectrumCode);

        /************************************************
         * 函数名   : setVersion
         * 输入参数 : 
           const QString& qstrVersion: 版本号
         * 输出参数 : NULL
         * 返回值   : void
         * 功能     : 设置版本号
         ************************************************/
        void setVersion(const QString& qstrVersion);

        /************************************************
         * 函数名   : setStationName
         * 输入参数 :
           const QString& qstrStationName: 站点名称
         * 输出参数 : NULL
         * 返回值   : void
         * 功能     : 设置站点名称
         ************************************************/
        void setStationName(const QString& qstrStationName);

        /************************************************
         * 函数名   : setStationCode
         * 输入参数 :
           const QString& qstrStationCode: 站点编码
         * 输出参数 : NULL
         * 返回值   : void
         * 功能     : 设置站点编码
         ************************************************/
        void setStationCode(const QString& qstrStationCode);

        /************************************************
         * 函数名   : setWeather
         * 输入参数 :
           const Weather eWeather: 天气
         * 输出参数 : NULL
         * 返回值   : void
         * 功能     : 设置天气
         ************************************************/
        void setWeather(const Weather eWeather);

        /************************************************
         * 函数名   : setTemperature
         * 输入参数 :
           const float fTemperature: 温度
         * 输出参数 : NULL
         * 返回值   : void
         * 功能     : 设置温度
         ************************************************/
        void setTemperature(const float fTemperature);

        /************************************************
         * 函数名   : setHumidity
         * 输入参数 :
           const qint8 cHumidity: 湿度
         * 输出参数 : NULL
         * 返回值   : void
         * 功能     : 设置湿度
         ************************************************/
        void setHumidity(const qint8 cHumidity);

        /************************************************
         * 函数名   : setInstrumentManufacturer
         * 输入参数 :
           const QString& qstrInstrumentManufacturer: 仪器厂家
         * 输出参数 : NULL
         * 返回值   : void
         * 功能     : 设置仪器厂家
         ************************************************/
        void setInstrumentManufacturer(const QString& qstrInstrumentManufacturer);

        /************************************************
         * 函数名   : setInstrumentModel
         * 输入参数 :
           const QString& qstrInstrumentModel: 仪器型号
         * 输出参数 : NULL
         * 返回值   : void
         * 功能     : 设置仪器型号
         ************************************************/
        void setInstrumentModel(const QString& qstrInstrumentModel);

        /************************************************
         * 函数名   : setInstrumentVersion
         * 输入参数 :
           const QString& qstrInstrumentVersion: 仪器版本号
         * 输出参数 : NULL
         * 返回值   : void
         * 功能     : 设置仪器版本号
         ************************************************/
        void setInstrumentVersion(const QString& qstrInstrumentVersion);

        /************************************************
         * 函数名   : setInstrumentSerialNumber
         * 输入参数 :
           const QString& qstrInstrumentSerialNumber: 仪器序列号
         * 输出参数 : NULL
         * 返回值   : void
         * 功能     : 设置仪器序列号
         ************************************************/
        void setInstrumentSerialNumber(const QString& qstrInstrumentSerialNumber);

        /************************************************
         * 函数名   : setSystemFrequency
         * 输入参数 :
           const float fSystemFrequency: 系统频率
         * 输出参数 : NULL
         * 返回值   : void
         * 功能     : 设置系统频率
         ************************************************/
        void setSystemFrequency(const float fSystemFrequency);

        /************************************************
         * 函数名   : setCompanyCode
         * 输入参数 :
           const QString& qstrCompanyCode: 公司代码
         * 输出参数 : NULL
         * 返回值   : void
         * 功能     : 设置公司代码
         ************************************************/
        void setCompanyCode(const QString& qstrCompanyCode);

        /************************************************
         * 函数名   : setInternalVersion
         * 输入参数 :
           const QString& qstrInternalVersion: 内部版本号
         * 输出参数 : NULL
         * 返回值   : void
         * 功能     : 设置内部版本号
         ************************************************/
        void setInternalVersion(const QString& qstrInternalVersion);

        /************************************************
         * 函数名   : getSpectrumDataFileHead
         * 输入参数 : NULL
         * 输出参数 : 
           SpectrumDataFileHead& stSpectrumDataFileHead: 图谱数据文件头结构体
         * 返回值   : void
         * 功能     : 获取图谱数据文件头
         ************************************************/
        void getSpectrumDataFileHead(SpectrumDataFileHead& stSpectrumDataFileHead);

        //////////////////////////////////////////////////////////////////////////
        // 文件操作

        /************************************************
         * 函数名   : saveAsBinary
         * 输入参数 : 
           const QString& qstrFilePath: 保存的文件路径
         * 输出参数 : NULL
         * 返回值   : bool
         * 功能     : 保存成二进制文件
         ************************************************/
        bool saveAsBinary(const QString& qstrFilePath);

        /************************************************
         * 函数名   : saveAsXML
         * 输入参数 :
           const QString& qstrFilePath: 保存的文件路径
           const bool bCrypt: 是否加密
         * 输出参数 : NULL
         * 返回值   : bool
         * 功能     : 保存成XML文件
         ************************************************/
        bool saveAsXML(const QString& qstrFilePath, const bool bCrypt = true);

        /************************************************
         * 函数名   : saveAsJSON
         * 输入参数 :
           const QString& qstrFilePath: 保存的文件路径
           const bool bCrypt: 是否加密
         * 输出参数 : NULL
         * 返回值   : bool
         * 功能     : 保存成JSON文件
         ************************************************/
        bool saveAsJSON(const QString& qstrFilePath, const bool bCrypt = true);


        /************************************************
         * 函数名   : parseBinaryFromFile
         * 输入参数 :
           const QString& qstrFilePath: 文件路径
           const bool bCrypt: 是否加密
         * 输出参数 : NULL
         * 返回值   : bool
         * 功能     : 从文件解析二进制数据
         ************************************************/
        bool parseBinaryFromFile(const QString& qstrFilePath, const bool bCrypt = true);

        /************************************************
         * 函数名   : parseXMLFromFile
         * 输入参数 :
           const QString& qstrFilePath: 保存的文件路径
           const bool bCrypt: 是否加密
           const EncodeFormat eEncodeFormat: 编码格式
         * 输出参数 : NULL
         * 返回值   : bool
         * 功能     : 从文件解析XML数据
         ************************************************/
        bool parseXMLFromFile(const QString& qstrFilePath, const bool bCrypt = true, const EncodeFormat eEncodeFormat = ENCODE_UTF8);

        /************************************************
         * 函数名   : parseJSONFromFile
         * 输入参数 :
           const QString& qstrFilePath: 保存的文件路径
           const bool bCrypt: 是否加密
           const EncodeFormat eEncodeFormat: 编码格式
         * 输出参数 : NULL
         * 返回值   : bool
         * 功能     : 从文件解析JSON数据
         ************************************************/
        bool parseJSONFromFile(const QString& qstrFilePath, const bool bCrypt = true, const EncodeFormat eEncodeFormat = ENCODE_UTF8);

        /************************************************
         * 函数名   : parseBinaryData
         * 输入参数 :
           const QByteArray& qbaData: 二进制数据
           const bool bCrypt: 是否加密
         * 输出参数 : NULL
         * 返回值   : bool
         * 功能     : 解析二进制数据
         ************************************************/
        bool parseBinaryData(const QByteArray& qbaData, const bool bCrypt = true);

        /************************************************
         * 函数名   : parseXMLData
         * 输入参数 :
           const QByteArray& qbaData: 二进制数据
           const bool bCrypt: 是否加密
           const EncodeFormat eEncodeFormat: 编码格式
         * 输出参数 : NULL
         * 返回值   : bool
         * 功能     : 解析XML数据
         ************************************************/
        bool parseXMLData(const QByteArray& qbaData, const bool bCrypt = true, const EncodeFormat eEncodeFormat = ENCODE_UTF8);

        /************************************************
         * 函数名   : parseJSONData
         * 输入参数 :
           const QByteArray& qbaData: 二进制数据
           const bool bCrypt: 是否加密
           const EncodeFormat eEncodeFormat: 编码格式
         * 输出参数 : NULL
         * 返回值   : bool
         * 功能     : 解析JSON数据
         ************************************************/
        bool parseJSONData(const QByteArray& qbaData, const bool bCrypt = true, const EncodeFormat eEncodeFormat = ENCODE_UTF8);


        /************************************************
         * 函数名   : encodeToBinary
         * 输入参数 : NULL
         * 输出参数 : NULL
         * 返回值   : QByteArray
         * 功能     : 将数据组织成二进制形式
         ************************************************/
        QByteArray encodeToBinary();

        /************************************************
         * 函数名   : encodeToXML
         * 输入参数 :
           const bool bCrypt: 是否加密
           const EncodeFormat eEncodeFormat: 编码格式
         * 输出参数 : NULL
         * 返回值   : QByteArray
         * 功能     : 将数据组织成xml形式
         ************************************************/
        QByteArray encodeToXML(const bool bCrypt = true, const EncodeFormat eEncodeFormat = ENCODE_UTF8);

        /************************************************
         * 函数名   : encodeToJSON
         * 输入参数 :
           const bool bCrypt: 是否加密
           const EncodeFormat eEncodeFormat: 编码格式
         * 输出参数 : NULL
         * 返回值   : QByteArray
         * 功能     : 将数据组织成JSON形式
         ************************************************/
        QByteArray encodeToJSON(const bool bCrypt = true, const EncodeFormat eEncodeFormat = ENCODE_UTF8);

    private:
        /************************************************
         * 函数名   : saveBinaryFileHead
         * 输入参数 :
           QByteArray& qbaPackage: 数据
         * 输出参数 : NULL
         * 返回值   : void
         * 功能     : 保存二进制文件头部
         ************************************************/
        void saveBinaryFileHead(QByteArray& qbaPackage);

        /************************************************
         * 函数名   : saveXMLFileHead
         * 输入参数 :
           XMLDocument& xmlDocumentObj: xml文档对象
         * 输出参数 : NULL
         * 返回值   : void
         * 功能     : 保存XML文件头部
         ************************************************/
        void saveXMLFileHead(XMLDocument& xmlDocumentObj);

        /************************************************
         * 函数名   : saveJSONFileHead
         * 输入参数 : NULL
         * 输出参数 :
           rapidjson::Document::AllocatorType& alloc:
           rapidjson::Value& jsonValue: json数据
         * 返回值   : void
         * 功能     : 保存JSON文件头部
         ************************************************/
        void saveJSONFileHead(rapidjson::Document::AllocatorType& alloc, rapidjson::Value& jsonValue);

        /************************************************
         * 函数名   : saveBinaryFileTail
         * 输入参数 :
           QByteArray& qbaPackage: 数据
         * 输出参数 : NULL
         * 返回值   : void
         * 功能     : 保存二进制文件尾部
         ************************************************/
        void saveBinaryFileTail(QByteArray& qbaPackage);

        /************************************************
         * 函数名   : updateBinaryFileLength
         * 输入参数 :
           QByteArray& qbaPackage: 数据
         * 输出参数 : NULL
         * 返回值   : void
         * 功能     : 更新二进制文件长度
         ************************************************/
        void updateBinaryFileLength(QByteArray& qbaPackage);

        /************************************************
         * 函数名   : parseBinaryFileHead
         * 输入参数 :
           const QByteArray& qbaPackage: 数据
         * 输出参数 : NULL
         * 返回值   : bool
         * 功能     : 解析二进制文件头部
         ************************************************/
        bool parseBinaryFileHead(const QByteArray& qbaPackage);

        /************************************************
         * 函数名   : parseXMLFileHead
         * 输入参数 :
           XMLDocument& xmlDocumentObj: xml文档对象
         * 输出参数 : NULL
         * 返回值   : bool
         * 功能     : 解析XML文件头部
         ************************************************/
        bool parseXMLFileHead(XMLDocument& xmlDocumentObj);

        /************************************************
         * 函数名   : parseJSONFileHead
         * 输入参数 :
           const rapidjson::Value& jsonValue: json数据
         * 输出参数 : NULL
         * 返回值   : bool
         * 功能     : 解析JSON文件头部
         ************************************************/
        bool parseJSONFileHead(const rapidjson::Value& jsonValue);

        /************************************************
         * 函数名   : parseBinarySpectrumsData
         * 输入参数 :
           const QByteArray& qbaPackage: 数据
         * 输出参数 : NULL
         * 返回值   : bool
         * 功能     : 解析二进制文件图谱数据
         ************************************************/
        bool parseBinarySpectrumsData(const QByteArray& qbaPackage);

        /************************************************
         * 函数名   : parseJSONSpectrumsData
         * 输入参数 :
           const rapidjson::Value& jsonValue: json数据
         * 输出参数 : NULL
         * 返回值   : bool
         * 功能     : 解析JSON文件图谱数据
         ************************************************/
        bool parseJSONSpectrumsData(const rapidjson::Value& jsonValue);

        /************************************************
         * 函数名   : checkBinaryCRC32
         * 输入参数 :
           const QByteArray& qbaPackage: 数据
         * 输出参数 : NULL
         * 返回值   : bool
         * 功能     : 校验二进制数据
         ************************************************/
        bool checkBinaryCRC32(const QByteArray& qbaPackage);

        /************************************************
         * 函数名   : checkJSONCRC32
         * 输入参数 :
           rapidjson::Document& doc: 数据
         * 输出参数 : NULL
         * 返回值   : bool
         * 功能     : 校验JSON数据
         ************************************************/
        bool checkJSONCRC32(rapidjson::Document& doc);

        /************************************************
         * 函数名   : clearSpectrums
         * 输入参数 : NULL
         * 输出参数 : NULL
         * 返回值   : bool
         * 功能     : 清除图谱对象
         ************************************************/
        void clearSpectrums();

    public:
        DataSpecificationPrivate* m_pDataSpecificationPrivate{ Q_NULLPTR };

        DataSpecificationVersion m_eDataSpecificationVersion;
    };
}
